package org.dromara.house.service.impl;


import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.file.FileNameUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.servlet.http.HttpServletResponse;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.domain.model.LoginUser;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.house.domain.bo.LeasingTrendsBo;
import org.dromara.house.domain.bo.ParkHousingBo;
import org.dromara.house.domain.bo.ParkHousingFileBo;
import org.dromara.house.domain.dto.DetailsDto;
import org.dromara.house.domain.dto.HousingDetailsDto;
import org.dromara.house.domain.entity.ParkFile;
import org.dromara.house.domain.entity.ParkFloor;
import org.dromara.house.domain.entity.ParkHousing;
import org.dromara.house.domain.entity.ParkHousingFile;
import org.dromara.house.mapper.ParkFileMapper;
import org.dromara.house.mapper.ParkFloorMapper;
import org.dromara.house.mapper.ParkHousingFileMapper;
import org.dromara.house.mapper.ParkHousingMapper;
import org.dromara.house.service.ParkHousingService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * <p>
 * 房源表 服务实现类
 * </p>
 *
 * @author LCH
 * @since 2025-08-26
 */
@Service
public class ParkHousingServiceImpl extends ServiceImpl<ParkHousingMapper, ParkHousing> implements ParkHousingService {

    @Value("${local.server.file.path}")
    private String fileUploadPath;

    @Autowired
    private ParkFileMapper parkFileMapper;

    @Autowired
    private ParkHousingFileMapper parkHousingFileMapper;

    @Autowired
    private ParkFloorMapper parkFloorMapper;

    @Override
    public TableDataInfo<ParkHousing> selectPageList(ParkHousingBo bo, PageQuery pageQuery) {
        Page<ParkHousing> page = baseMapper.selectPageList(bo, pageQuery.build());
        for (ParkHousing record : page.getRecords()) {
            //查询出房源对应的实景图
            List<ParkFile> files = parkFileMapper.selectListByHousingId(record.getId());
            record.setFiles(files);
        }
        return TableDataInfo.build(page);
    }

    @Override
    public ParkHousing selectById(Long id) {
        ParkHousing parkHousing = baseMapper.selectById(id);
        List<ParkFile> files = parkFileMapper.selectListByHousingId(id);
        parkHousing.setFiles(files);
        //查询总面积、已出租面积、楼宇房间详情列表
        LeasingTrendsBo bo = new LeasingTrendsBo();
        bo.setDistrictId(parkHousing.getDistrictId());
        bo.setHousingId(id);
        Double totalArea = parkHousing.getTotalArea();
        //已租赁面积
        Double leaseArea = baseMapper.queryLeaseArea(bo);
        parkHousing.setUnreleasedArea(totalArea-leaseArea);
        parkHousing.setTotalArea(totalArea);
        parkHousing.setLeasedArea(leaseArea);
        LambdaQueryWrapper<ParkFloor> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ParkFloor::getHousingId, id);
        wrapper.orderByAsc(ParkFloor::getSortId);
        List<ParkFloor> parkFloors = parkFloorMapper.selectList(wrapper);
        parkHousing.setHouseFloorDtoList(parkFloors);

        return parkHousing;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertParkHousing(ParkHousing parkHousing) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        parkHousing.setCreateTime(new Date());
        parkHousing.setCreateBy(loginUser.getUserId());
        parkHousing.setDeleteStatus(0);
        int insert = baseMapper.insert(parkHousing);
        //处理楼宇图片信息接口
        for (ParkFile file : parkHousing.getFiles()) {
            ParkHousingFile parkHousingFile = new ParkHousingFile();
            parkHousingFile.setHousingId(parkHousing.getId());
            parkHousingFile.setFileId(file.getId());
            parkHousingFile.setDeleteStatus(0);
            parkHousingFileMapper.insert(parkHousingFile);
            //给图片添加备注
            parkFileMapper.updateById(file);

        }

        return insert;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateParkHousing(ParkHousing parkHousing) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        parkHousing.setUpdateTime(new Date());
        parkHousing.setUpdateBy(loginUser.getUserId());

        LambdaUpdateWrapper<ParkHousingFile> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(ParkHousingFile::getHousingId, parkHousing.getId());
        ParkHousingFile parkHousingFile = new ParkHousingFile();
        parkHousingFile.setDeleteStatus(1);
        parkHousingFileMapper.update(parkHousingFile, updateWrapper);
        //删除图片记录，重新添加
        for (ParkFile file : parkHousing.getFiles()) {
            ParkHousingFile file1 = new ParkHousingFile();
            file1.setHousingId(parkHousing.getId());
            file1.setFileId(file.getId());
            file1.setDeleteStatus(0);
            parkHousingFileMapper.insert(file1);
            //给图片添加备注
            parkFileMapper.updateById(file);
        }
        return baseMapper.updateById(parkHousing);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteByIds(Long[] ids) {
        for (Long id : ids) {
            ParkHousing parkHousing = baseMapper.selectById(id);
            parkHousing.setDeleteStatus(1);
            baseMapper.updateById(parkHousing);
        }
        return 1;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R<ParkFile> uploadImage(MultipartFile file) {
        try {
            // 1. 校验文件是否为空
            if (file.isEmpty()) {
                throw new RuntimeException("请选择要上传的文件");
            }

            // 2. 校验文件类型（只允许图片）
            String contentType = file.getContentType();
            if (contentType == null || !contentType.startsWith("image/")) {
                throw new RuntimeException("只允许上传图片文件");
            }

            // 3. 生成唯一文件名（防止重名）
            String originalFilename = file.getOriginalFilename();
            String fileExtension = FileNameUtil.extName(originalFilename); // 输出 "jpg"
            String newFileName = UUID.randomUUID().toString() + "." + fileExtension;
            String today = DateUtil.today() + "/";
            // 4. 创建目标路径
            Path uploadPath = Paths.get(fileUploadPath + today);
            if (!Files.exists(uploadPath)) {
                Files.createDirectories(uploadPath);
            }

            // 5. 保存文件
            Path filePath = uploadPath.resolve(newFileName);
            file.transferTo(filePath);
            ParkFile parkFile = new ParkFile();
            parkFile.setFileName(newFileName);
            parkFile.setFilePath(today + newFileName);
            parkFile.setCreateTime(new Date());
            int insert = parkFileMapper.insert(parkFile);

            return R.ok(parkFile);
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("文件上传失败: " + e.getMessage());
        }
    }

    @Override
    public void downloadImage(String fileId, HttpServletResponse response) {
        ParkFile parkFile = parkFileMapper.selectById(fileId);
        String filePath = fileUploadPath + parkFile.getFilePath();
        File file = new File(filePath);
        String s = file.getName().split("\\.")[1];
        String contentType = getImageContentType(s);
        response.setContentType(contentType);
        response.setHeader("Content-Disposition",
            "attachment; filename=\"" + file.getName() + "\"");
        response.setContentLength((int) file.length());

        // 使用缓冲流提高性能
        try (InputStream in = new BufferedInputStream(Files.newInputStream(file.toPath()));
             OutputStream out = new BufferedOutputStream(response.getOutputStream())) {

            byte[] buffer = new byte[1024]; // 8KB缓冲区
            int bytesRead;
            while ((bytesRead = in.read(buffer)) != -1) {
                out.write(buffer, 0, bytesRead);
            }
            out.flush();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public R<Void> saveImage(ParkHousingFileBo bo) {
        ParkHousingFile parkHousingFile = new ParkHousingFile();
        parkHousingFile.setHousingId(bo.getHousingId());
        parkHousingFile.setFileId(bo.getFileId());
        parkHousingFile.setDeleteStatus(0);
        parkHousingFileMapper.insert(parkHousingFile);
        return R.ok();
    }

    /**
     * 删除对应图片
     *
     * @param bo
     * @return
     */
    @Override
    public R<Void> deleteImage(ParkHousingFileBo bo) {
        ParkHousingFile parkHousingFile = parkHousingFileMapper.selectById(bo.getId());
        parkHousingFile.setDeleteStatus(1);
        parkHousingFileMapper.updateById(parkHousingFile);
        return R.ok();
    }

    /**
     * 查询每层的总面积，已出租面积
     * @param bo
     * @return
     */
    @Override
    public DetailsDto getDetails(ParkHousingBo parkHousingBo) {
        ParkFloor parkFloor = parkFloorMapper.selectById(parkHousingBo.getFloor());
        DetailsDto dto = new DetailsDto();
        LeasingTrendsBo bo = new LeasingTrendsBo();
        bo.setDistrictId(parkHousingBo.getDistrictId());
        bo.setHousingId(parkHousingBo.getHousingId());
        bo.setFloor(parkHousingBo.getFloor());
        //总面积
        Double totalArea = parkFloor.getFloorArea();
        //已租赁面积
        Double leaseArea = baseMapper.queryLeaseArea(bo);
        //未租赁面积
        Double unLeaseArea = totalArea-leaseArea;

        //查询楼层中租赁的企业列表
        List<HousingDetailsDto> detailsDtoList = baseMapper.selectHousingDetailsDto(bo);
        dto.setTotalArea(totalArea);
        dto.setLeasedArea(leaseArea);
        dto.setUnreleasedArea(unLeaseArea);
        dto.setDetailsDtoList(detailsDtoList);

        return dto;
    }

    private String getImageContentType(String s) {
        if (s.equals("jpg") || s.equals("jpeg")) {
            return "image/jpeg";
        } else if (s.equals("png")) {
            return "image/png";
        } else if (s.equals("gif")) {
            return "image/gif";
        } else if (s.equals("tiff") || s.equals("tif")) {
            return "image/tiff";
        } else if (s.equals("svg")) {
            return "image/svg+xml";
        } else if (s.equals("bmp")) {
            return "image/bmp";
        } else if (s.equals("ico")) {
            return "image/x-icon";
        } else if (s.equals("webp")) {
            return "image/webp";
        }
        return "image/png";
    }

    private Wrapper<ParkHousing> buildQueryWrapper(ParkHousingBo bo) {
        LambdaQueryWrapper<ParkHousing> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(ObjectUtil.isNotEmpty(bo.getHousingName()), ParkHousing::getHousingName, bo.getHousingName());
        wrapper.eq(ParkHousing::getDeleteStatus, 0);
        return wrapper;
    }
}
